##################################################################
# File : /lua/ui/network/gameserver.lua
# Description : Dark Skies networking module
# Author : Neruz
##################################################################

local internalComm = import('/lua/ui/network/lobbycomm.lua')

PlayerSyncMeta = {
    __index = function(t, key)
        local id = rawget(t, 'id')
        return DSSocket.players[id][key]
    end,

    __newindex = function(t, key, val)
        #LOG( "SYNC: " .. key .. ' = ' .. repr(val))
        local id = rawget(t, 'id')
        DSSocket.players[key] = val
		DSSocket:BroadcastData({_type = "PlayerSync", playerId = key, playerData = val})
    end,
}

GameServer = Class(internalComm.LobbyComm) {

    Hosting = function(self)
    	_G.DSSocket = self
        local localPlayerId = self:GetLocalPlayerID()
    	self.players = {}
    	self._callbacks = {}
    	self.PlayerSync = {}
    	self.PlayerSync.id = localPlayerId
    	setmetatable(self.PlayerSync, PlayerSyncMeta)
    	local localArmyData = GetArmiesTable()["armiesTable"][1]
        local localPlayerName = self:GetLocalPlayerName()
    	self.PlayerSync[localPlayerId] = {name = localPlayerName, playerId = localPlayerId, armyData = localArmyData}
        ForkThread(self._TimeoutThread, self)
    end,
    
    _TimeoutThread = function(self)
		while self do
			local peers = self:GetPeers()
			for k,peer in peers do
				if peer.quiet > DSinternalComm.quietTimeout then
					self:EjectPeer(peer.id, 'TimedOutToHost')
				end
			end
            WaitSeconds(1)
		end
    end,
    
    Bind = function(self, name, func)
    	table.insert(self._callbacks[name], func)
    end,
    
    Unbind = function(self, name, func)
    	table.removebyValue(self._callbacks[name], func)
    end,
    
	DataReceived = function(self, data)
		local _type = data._type
		local senderId = data.SenderID
		local senderName = data.SenderName
		if _type == "PlayerJoined" then
			local playerData = data.playerData
			local fixedPlayerName = self:MakeValidPlayerName(senderId, playerData.requestedName)
			local armyData = playerData.armyData
			local playerData = {name = fixedPlayerName, playerId = senderId, armyData = armyData}
			self:SendData(senderId, {_type = "PlayerInfo", players = self.players})
			self.PlayerSync[senderId] = playerData
-- 			local info = {
-- 				name = senderName,
-- 				playerId = senderId,
-- 				faction = armyData.faction,
-- 				text = "woo",
-- 			}
-- 			InfoModule.Update(info)
-- 	    	for i, func in self._callbacks['PlayerJoined'] do
-- 	    		func(peerId)
-- 	    	end
		elseif _type == "ChatMessage" then
			local chatData = data.ChatData
			import('/lua/ui/game/chat.lua').ReceiveChat(data.SenderName, chatData)
		end
	end,
	
	SendData = function(self, targetId, data)
		internalComm.LobbyComm.SendData(self, targetId, data)
	end,
	
	BroadcastData = function(self, data)
		internalComm.LobbyComm.BroadcastData(self, data)
	end,
	
	SystemMessage = function(self, text)
		LOG(repr(text))
	end,
	
    PeerDisconnected = function(self, peerName, peerId)
    	WARN('PeerDisconnected', peerName, peerId)
    	self.players[peerId] = nil
--     	for i, func in self._callbacks['PlayerLeft'] do
--     		func(peerId)
--     	end
    end,
    
    PeerConnected = function(self, peerName, peerId)
    	WARN('PeerConnected', peerName, peerId)
    end,
}

function InitGameServer(protocol, port)
    local comm = GameServer(protocol, port, internalComm.maxConnections, "gameServer", nil, nil)
    return comm
end